﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using AsyncPersistence.Common;

namespace AsyncPersistence.Services
{
    public class PersistenceExecutor : IPersistenceExecutor
    {
        #region Fields
        private Timer timer;
        private Queue<APersistenceTask> persistenceTasks;
        private int countTasks;
        private int countSave;
        #endregion

        #region Cosntructor
        public PersistenceExecutor()
        {
            int period = 250;
            persistenceTasks = new Queue<APersistenceTask>();
            timer = new Timer(ExecuteTasks, null, period, period);
            countTasks = 0;
            countSave = 0;
        }
        #endregion

        #region Public Methods
        public void AddPersistenceTask(APersistenceTask persistanceTask)
        {
            lock (this)
            {
                if (persistenceTasks.Any())
                {
                    var element = persistenceTasks.FirstOrDefault(e => e.EntityId() == persistanceTask.EntityId());
                    if (element != null)
                    {
                        if (persistanceTask.RequestTime > element.RequestTime)
                            persistenceTasks = new Queue<APersistenceTask>(persistenceTasks.Distinct(new PersistenceTaskComparer()));
                    }
                    else
                        persistenceTasks.Enqueue(persistanceTask);
                        
                }
                else
                    persistenceTasks.Enqueue(persistanceTask);
                countTasks++;
            }
        }

        public void Dispose()
        {
            if (timer != null)
                timer.Dispose();
        }

        public int GetCountTask()
        {
            lock (this)
            {
                return countTasks;
            }
        }

        public int GetCountSave()
        {
            lock (this)
            {
                return countSave;
            }
        }

        #endregion

        #region Private Methods
        private void ExecuteTasks(object state)
        {
            lock (this)
            {
                while (persistenceTasks.Any())
                {
                    var task = persistenceTasks.Dequeue();
                    task.Execute();
                    countSave++;
                }
            }
        }
        #endregion
    }
}
